import { Context, Next } from 'koa';

/**
 * 验证规则接口
 */
export interface ValidationRule {
  field: string;
  required?: boolean;
  type?: 'string' | 'number' | 'boolean' | 'email' | 'url' | 'objectId';
  minLength?: number;
  maxLength?: number;
  min?: number;
  max?: number;
  pattern?: RegExp;
  custom?: (value: any) => boolean | string;
  message?: string;
}

/**
 * 验证错误接口
 */
export interface ValidationError {
  field: string;
  message: string;
  value?: any;
}

/**
 * 验证结果接口
 */
export interface ValidationResult {
  valid: boolean;
  errors: ValidationError[];
  data?: any;
}

/**
 * 验证器类
 */
export class Validator {
  /**
   * 验证数据
   */
  static validate(data: any, rules: ValidationRule[]): ValidationResult {
    const errors: ValidationError[] = [];
    const validatedData: any = {};

    for (const rule of rules) {
      const value = data[rule.field];
      const error = this.validateField(rule.field, value, rule);

      if (error) {
        errors.push(error);
      } else {
        validatedData[rule.field] = value;
      }
    }

    return {
      valid: errors.length === 0,
      errors,
      data: validatedData
    };
  }

  /**
   * 验证单个字段
   */
  private static validateField(field: string, value: any, rule: ValidationRule): ValidationError | null {
    // 检查必填
    if (rule.required && (value === undefined || value === null || value === '')) {
      return {
        field,
        message: rule.message || `参数 '${field}' 是必填项，不能为空`,
        value,
        validationType: 'required',
        expected: '非空值'
      } as ValidationError & { validationType: string; expected: string };
    }

    // 如果值为空且非必填，跳过其他验证
    if (!rule.required && (value === undefined || value === null || value === '')) {
      return null;
    }

    // 类型验证
    if (rule.type) {
      const typeError = this.validateType(field, value, rule.type, rule.message);
      if (typeError) return typeError;
    }
    
    // 长度验证（字符串）
    if (typeof value === 'string') {
      if (rule.minLength !== undefined && value.length < rule.minLength) {
        return {
          field,
          message: rule.message || `参数 '${field}' 长度不能少于 ${rule.minLength} 个字符，当前长度: ${value.length}`,
          value,
          validationType: 'minLength',
          expected: `最少 ${rule.minLength} 个字符`,
          actual: `${value.length} 个字符`
        } as ValidationError & { validationType: string; expected: string; actual: string };
      }

      if (rule.maxLength !== undefined && value.length > rule.maxLength) {
        return {
          field,
          message: rule.message || `参数 '${field}' 长度不能超过 ${rule.maxLength} 个字符，当前长度: ${value.length}`,
          value,
          validationType: 'maxLength',
          expected: `最多 ${rule.maxLength} 个字符`,
          actual: `${value.length} 个字符`
        } as ValidationError & { validationType: string; expected: string; actual: string };
      }
    }

    // 数值范围验证
    if (typeof value === 'number') {
      if (rule.min !== undefined && value < rule.min) {
        return {
          field,
          message: rule.message || `参数 '${field}' 不能小于 ${rule.min}，当前值: ${value}`,
          value,
          validationType: 'min',
          expected: `>= ${rule.min}`,
          actual: value.toString()
        } as ValidationError & { validationType: string; expected: string; actual: string };
      }

      if (rule.max !== undefined && value > rule.max) {
        return {
          field,
          message: rule.message || `参数 '${field}' 不能大于 ${rule.max}，当前值: ${value}`,
          value,
          validationType: 'max',
          expected: `<= ${rule.max}`,
          actual: value.toString()
        } as ValidationError & { validationType: string; expected: string; actual: string };
      }
    }

    // 正则表达式验证
    if (rule.pattern && typeof value === 'string') {
      if (!rule.pattern.test(value)) {
        return {
          field,
          message: rule.message || `参数 '${field}' 格式不正确，当前值: '${value}'`,
          value,
          validationType: 'pattern',
          expected: `匹配正则表达式: ${rule.pattern.toString()}`,
          actual: `'${value}'`
        } as ValidationError & { validationType: string; expected: string; actual: string };
      }
    }

    // 自定义验证
    if (rule.custom) {
      const customResult = rule.custom(value);
      if (customResult !== true) {
        return {
          field,
          message: typeof customResult === 'string' ? customResult : (rule.message || `参数 '${field}' 自定义验证失败`),
          value,
          validationType: 'custom',
          expected: '通过自定义验证',
          actual: `验证失败: ${value}`
        } as ValidationError & { validationType: string; expected: string; actual: string };
      }
    }

    return null;
  }

  /**
   * 验证数据类型
   */
  private static validateType(field: string, value: any, type: string, message?: string): ValidationError | null {
    switch (type) {
      case 'string':
        if (typeof value !== 'string') {
          return {
            field,
            message: message || `参数 '${field}' 必须是字符串类型，当前类型: ${typeof value}`,
            value,
            validationType: 'type',
            expected: 'string',
            actual: typeof value
          } as ValidationError & { validationType: string; expected: string; actual: string };
        }
        break;

      case 'number':
        if (typeof value !== 'number' || isNaN(value)) {
          return {
            field,
            message: message || `参数 '${field}' 必须是数字类型，当前类型: ${typeof value}`,
            value,
            validationType: 'type',
            expected: 'number',
            actual: typeof value
          } as ValidationError & { validationType: string; expected: string; actual: string };
        }
        break;

      case 'boolean':
        if (typeof value !== 'boolean') {
          return {
            field,
            message: message || `参数 '${field}' 必须是布尔值类型，当前类型: ${typeof value}`,
            value,
            validationType: 'type',
            expected: 'boolean',
            actual: typeof value
          } as ValidationError & { validationType: string; expected: string; actual: string };
        }
        break;

      case 'email':
        if (typeof value !== 'string' || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
          return {
            field,
            message: message || `参数 '${field}' 必须是有效的邮箱地址，当前值: '${value}'`,
            value,
            validationType: 'type',
            expected: '有效的邮箱格式 (example@domain.com)',
            actual: `'${value}'`
          } as ValidationError & { validationType: string; expected: string; actual: string };
        }
        break;

      case 'url':
        if (typeof value !== 'string') {
          return {
            field,
            message: message || `参数 '${field}' 必须是字符串类型，当前类型: ${typeof value}`,
            value,
            validationType: 'type',
            expected: 'string',
            actual: typeof value
          } as ValidationError & { validationType: string; expected: string; actual: string };
        }
        try {
          new URL(value);
        } catch {
          return {
            field,
            message: message || `参数 '${field}' 必须是有效的URL，当前值: '${value}'`,
            value,
            validationType: 'type',
            expected: '有效的URL格式 (http://example.com)',
            actual: `'${value}'`
          } as ValidationError & { validationType: string; expected: string; actual: string };
        }
        break;

      case 'objectId':
        if (typeof value !== 'string' || !/^[0-9a-fA-F]{24}$/.test(value)) {
          return {
            field,
            message: message || `参数 '${field}' 必须是有效的ObjectId，当前值: '${value}'`,
            value,
            validationType: 'type',
            expected: '24位十六进制字符串',
            actual: `'${value}'`
          } as ValidationError & { validationType: string; expected: string; actual: string };
        }
        break;
    }

    return null;
  }
}

/**
 * 请求验证中间件
 */
export function validateRequest(rules: ValidationRule[]) {
  return async (ctx: Context, next: Next) => {
    const data = {
      ...(ctx.request.body as any || {}),
      ...(ctx.query || {}),
      ...(ctx.params || {})
    };

    const result = Validator.validate(data, rules);

    if (!result.valid) {
      ctx.status = 400;
      const hasRequiredFieldError = result.errors.some(error => 
        error.message.includes('不能为空') || error.message.includes('必须') || error.message.includes('required')
      );
      ctx.body = {
        success: false,
        message: hasRequiredFieldError ? '必填字段验证失败' : '请求参数验证失败',
        errors: result.errors
      };
      return;
    }

    // 将验证后的数据存储到上下文
    ctx.state.validatedData = result.data;

    await next();
  };
}

/**
 * 常用验证规则
 */
export const CommonRules = {
  // 用户名验证
  username: {
    field: 'username',
    required: true,
    type: 'string' as const,
    minLength: 3,
    maxLength: 20,
    pattern: /^[a-zA-Z0-9_]+$/,
    message: '用户名必须是3-20位字母、数字或下划线'
  },

  // 密码验证
  password: {
    field: 'password',
    required: true,
    type: 'string' as const,
    minLength: 6,
    maxLength: 50,
    message: '密码长度必须在6-50位之间'
  },

  // 邮箱验证
  email: {
    field: 'email',
    required: true,
    type: 'email' as const,
    message: '请输入有效的邮箱地址'
  },

  // 手机号验证
  phone: {
    field: 'phone',
    required: false,
    type: 'string' as const,
    pattern: /^1[3-9]\d{9}$/,
    message: '请输入有效的手机号码'
  },

  // 系统代码验证
  systemCode: {
    field: 'systemCode',
    required: true,
    type: 'string' as const,
    minLength: 2,
    maxLength: 50,
    pattern: /^[a-zA-Z0-9_-]+$/,
    message: '系统代码必须是2-50位字母、数字、下划线或连字符'
  },

  // ObjectId验证
  objectId: (field: string, required: boolean = true) => ({
    field,
    required,
    type: 'objectId' as const,
    message: `${field}必须是有效的ID`
  })
};

export default validateRequest;
